{
  config,
  lib,
  pkgs,
  ...
}:
let
  CONTAINS_NEWLINE_RE = ".*\n.*";
  # The following values are reserved as complete option values:
  # { - start of a group.
  # """ - start of a multi-line string.
  RESERVED_VALUE_RE = "[[:space:]]*(\"\"\"|\\{)[[:space:]]*";
  NEEDS_MULTILINE_RE = "${CONTAINS_NEWLINE_RE}|${RESERVED_VALUE_RE}";

  # There is no way to encode """ on its own line in a Minetest config.
  UNESCAPABLE_RE = ".*\n\"\"\"\n.*";

  toConfMultiline =
    name: value:
    assert lib.assertMsg (
      (builtins.match UNESCAPABLE_RE value) == null
    ) ''""" can't be on its own line in a minetest config.'';
    "${name} = \"\"\"\n${value}\n\"\"\"\n";

  toConf =
    values:
    lib.concatStrings (
      lib.mapAttrsToList (
        name: value:
        {
          bool = "${name} = ${toString value}\n";
          int = "${name} = ${toString value}\n";
          null = "";
          set = "${name} = {\n${toConf value}}\n";
          string =
            if (builtins.match NEEDS_MULTILINE_RE value) != null then
              toConfMultiline name value
            else
              "${name} = ${value}\n";
        }
        .${builtins.typeOf value}
      ) values
    );

  cfg = config.services.minetest-server;
  flag =
    val: name:
    lib.optionals (val != null) [
      "--${name}"
      "${toString val}"
    ];

  flags = [
    "--server"
  ]
  ++ (
    if cfg.configPath != null then
      [
        "--config"
        cfg.configPath
      ]
    else
      [
        "--config"
        (builtins.toFile "minetest.conf" (toConf cfg.config))
      ]
  )
  ++ (flag cfg.gameId "gameid")
  ++ (flag cfg.world "world")
  ++ (flag cfg.logPath "logfile")
  ++ (flag cfg.port "port")
  ++ cfg.extraArgs;
in
{
  options = {
    services.minetest-server = {
      enable = lib.mkOption {
        type = lib.types.bool;
        default = false;
        description = "If enabled, starts a Minetest Server.";
      };

      gameId = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        default = null;
        description = ''
          Id of the game to use. To list available games run
          `minetestserver --gameid list`.

          If only one game exists, this option can be null.
        '';
      };

      world = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = ''
          Name of the world to use. To list available worlds run
          `minetestserver --world list`.

          If only one world exists, this option can be null.
        '';
      };

      configPath = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = ''
          Path to the config to use.

          If set to null, the config of the running user will be used:
          `~/.minetest/minetest.conf`.
        '';
      };

      config = lib.mkOption {
        type = lib.types.attrsOf lib.types.anything;
        default = { };
        description = ''
          Settings to add to the minetest config file.

          This option is ignored if `configPath` is set.
        '';
      };

      logPath = lib.mkOption {
        type = lib.types.nullOr lib.types.path;
        default = null;
        description = ''
          Path to logfile for logging.

          If set to null, logging will be output to stdout which means
          all output will be caught by systemd.
        '';
      };

      port = lib.mkOption {
        type = lib.types.nullOr lib.types.port;
        default = null;
        description = ''
          Port number to bind to.

          If set to null, the default 30000 will be used.
        '';
      };

      extraArgs = lib.mkOption {
        type = lib.types.listOf lib.types.str;
        default = [ ];
        description = ''
          Additional command line flags to pass to the minetest executable.
        '';
      };
    };
  };

  config = lib.mkIf cfg.enable {
    users.users.minetest = {
      description = "Minetest Server Service user";
      home = "/var/lib/minetest";
      createHome = true;
      uid = config.ids.uids.minetest;
      group = "minetest";
    };
    users.groups.minetest.gid = config.ids.gids.minetest;

    systemd.services.minetest-server = {
      description = "Minetest Server Service";
      wantedBy = [ "multi-user.target" ];
      after = [ "network.target" ];

      serviceConfig.Restart = "always";
      serviceConfig.User = "minetest";
      serviceConfig.Group = "minetest";
      serviceConfig.StateDirectory = "minetest";
      serviceConfig.WorkingDirectory = "/var/lib/minetest";
      serviceConfig.ExecStart = "${pkgs.luanti}/bin/luanti ${lib.escapeShellArgs flags}";
    };
  };
}
